Skip to content

feat(data): Add AseDataLoader utility with lazy loading for ase - #15

Merged
muhrin merged 1 commit into
camml-lab:developfrom
aychachouchene:feature/ase-dataloader
Jul 10, 2026
Merged

feat(data): Add AseDataLoader utility with lazy loading for ase#15
muhrin merged 1 commit into
camml-lab:developfrom
aychachouchene:feature/ase-dataloader

Conversation

@aychachouchene

Copy link
Copy Markdown
Collaborator

Lazy loader for ASE Atoms with optional conversion to jraph.GraphsTuple.

@codecov-commenter

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 34.14634% with 27 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
src/tensorial/gcnn/data/_ase.py 28.94% 27 Missing ⚠️
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Files with missing lines Coverage Δ
src/tensorial/gcnn/data/__init__.py 100.00% <100.00%> (ø)
src/tensorial/gcnn/data/_ase.py 28.94% <28.94%> (ø)
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@muhrin muhrin left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just a few changes to be made. Also, if you could turn on pre-commit checks that would be good, as some of them are failing for this PR. You can do this using:

pre-commit install

in the terminal. In case the pre-commit package is, itself, not installed, just go to your tensorial folder and do:

pip install -e .[dev]

Comment thread src/tensorial/gcnn/data/_ase.py Outdated
self._read_kwargs: Final[dict[str, Any]] = self._init_kwargs(limit, read_kwargs)

try:
import ase.io

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of doing this can you use the lazy import helper that I left in the chat. Basically, as a general rule it's not a good idea to do imports anywhere other than the top of the module file because it harms the readability of functions, and if we have everything at the top of the module it's easy to see all the direct dependencies of this module.

Here's the example:

import importlib.util
import sys

def lazy_import(name: str):
    """Lazily import a module using the standard library."""
    spec = importlib.util.find_spec(name)
    if spec is None:
        # Optimization: if it's completely missing, we can fail early 
        # or return a dummy object.
        pass
    loader = importlib.util.LazyLoader(spec.loader)
    module = importlib.util.module_from_spec(spec)
    spec.loader = loader
    sys.modules[name] = module
    return module

# Usage at top of file
np = lazy_import("numpy") 

Comment thread src/tensorial/gcnn/data/_ase.py Outdated
@@ -0,0 +1,77 @@
"""Module for loading ase.Atoms objects as graphs"""

import collections.abc

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This you can change to from collections.abc import Sequence

Comment thread src/tensorial/gcnn/data/_ase.py Outdated
__all__ = ("AseDataLoader",)


class AseDataLoader(collections.abc.Sequence[jraph.GraphsTuple]):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and here the parent class can just be Sequence[jraph.GraphsTuple]

Comment thread src/tensorial/gcnn/data/_ase.py Outdated
from typing import TYPE_CHECKING, Any, Final

import jraph
from tensorial import gcnn

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You cannot import gcnn this way, because you are 'inside' gcnn and so this creates a cyclic import dependency.

Instead what you can do is from .. import atomic which is now relative (and specific), hence avoiding the cyclic import.

Comment thread src/tensorial/gcnn/data/_ase.py Outdated
entry = self._data[item]
if self._to_graphs and not isinstance(entry, jraph.GraphsTuple):
# Lazily convert the first time
entry = gcnn.atomic.graph_from_ase(entry, **self._to_graphs)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

...and here you just remove gcnn and call atomic.graph_from... directly.

@aychachouchene
aychachouchene force-pushed the feature/ase-dataloader branch from bc1e48e to 8f60ddf Compare July 10, 2026 11:03
@muhrin

muhrin commented Jul 10, 2026

Copy link
Copy Markdown
Member

Thanks!

@muhrin
muhrin merged commit 12f582f into camml-lab:develop Jul 10, 2026
4 of 9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants